package se.webbzon.oschi01.collision3d;

import java.util.ArrayList;
import java.util.Collection;

import javax.vecmath.Point3d;

public class CollisionCylinder3D extends CollisionModel3D {

	/*============================================================
	Constructors
	============================================================*/
	
	/** Creates a new collision cylinder with height 1 and radius 0.5.
	 * The center of the cylinder will be placed in (0,0,0). The
	 * number of divisions (sides) is given by the input. No
	 * cylinder bases will be created if the cylinder is open. **/
	public CollisionCylinder3D(boolean open) {
		this(open,18);
	}
	
	/** Creates a new collision cylinder with height 1 and radius 0.5.
	 * The center of the cylinder will be placed in (0,0,0). The
	 * number of divisions (sides) will be equal to 18. No
	 * cylinder bases will be created if the cylinder is open. **/
	public CollisionCylinder3D(boolean open, int divisions) {
		this(open,1,0.5,divisions);
	}
	
	/** Creates a new collision cylinder with a given height and radius.
	 * The center of the cylinder will be placed in (0,0,0) and the
	 * number of divisions if given by the input. No cylinder bases
	 * will be created if the cylinder is open. **/
	public CollisionCylinder3D(boolean open, double height, double radius, int divisions) {
		super(open ? 	createModelOpen(height,radius,divisions) : 
						createModelClosed(height,radius,divisions));
	}
	
	/*============================================================
	Private Methods
	============================================================*/
	
	/** Creates the closed collision model. **/
	private static Collection<CollisionTriangle3D> createModelClosed(
																double height,
																double radius,
																int divisions) {
		final double h = height/2, dv = 2*Math.PI/divisions;
		final Point3d top = new Point3d(0,h,0);
		final Point3d bottom = new Point3d(0,-h,0);
		final Point3d at = new Point3d(radius,h,0);
		final Point3d ab = new Point3d(radius,-h,0);
		final Point3d bt = new Point3d();
		final Point3d bb = new Point3d();
		final ArrayList<CollisionTriangle3D> vertices = 
				new ArrayList<CollisionTriangle3D>();
		
		// Shape the cylinder
		for (int i = 0; i < divisions; i++) {
			final double rcos = radius*Math.cos(i*dv), rsin = radius*Math.sin(i*dv);
			bt.set(rcos,h,rsin);
			bb.set(rcos,-h,rsin);
			vertices.add(new CollisionTriangle3D(at,ab,bb));
			vertices.add(new CollisionTriangle3D(at,bt,bb));
			vertices.add(new CollisionTriangle3D(top,at,bt));
			vertices.add(new CollisionTriangle3D(bottom,ab,bb));
			at.set(bt);
			ab.set(bb);
		}
		
		// Close the cylinder
		bt.set(radius,h,0);
		bb.set(radius,-h,0);
		vertices.add(new CollisionTriangle3D(at,ab,bb));
		vertices.add(new CollisionTriangle3D(at,bt,bb));
		vertices.add(new CollisionTriangle3D(top,at,bt));
		vertices.add(new CollisionTriangle3D(bottom,ab,bb));

		return vertices;
	}
	
	/** Creates the open collision model. **/
	private static Collection<CollisionTriangle3D> createModelOpen(
																double height,
																double radius,
																int divisions) {
		final double h = height/2, dv = 2*Math.PI/divisions;
		final Point3d at = new Point3d(radius,h,0);
		final Point3d ab = new Point3d(radius,-h,0);
		final Point3d bt = new Point3d();
		final Point3d bb = new Point3d();
		final ArrayList<CollisionTriangle3D> vertices = 
				new ArrayList<CollisionTriangle3D>();
		
		// Shape the cylinder
		for (int i = 0; i < divisions; i++) {
			final double rcos = radius*Math.cos(i*dv), rsin = radius*Math.sin(i*dv);
			bt.set(rcos,h,rsin);
			bb.set(rcos,-h,rsin);
			vertices.add(new CollisionTriangle3D(at,ab,bb));
			vertices.add(new CollisionTriangle3D(at,bt,bb));
			at.set(bt);
			ab.set(bb);
		}
		
		// Close the cylinder
		bt.set(radius,h,0);
		bb.set(radius,-h,0);
		vertices.add(new CollisionTriangle3D(at,ab,bb));
		vertices.add(new CollisionTriangle3D(at,bt,bb));
	
		return vertices;
	}
	
}
